package ver

import (
	"fmt"
	"strconv"
	"strings"
)

type Version struct {
	String        string   // 字符串形式
	Major         int      // 主版本号
	Minor         int      // 次版本号
	Patch         int      // 补丁版本号
	PreRelease    []string // -先行版本号 [0-9A-Za-z-]
	BuildMetadata []string // +编译元数据 [0-9A-Za-z-]
}

func parseCore(s string) ([]int, error) {
	items := strings.Split(s, ".")
	if len(items) != 3 {
		return nil, fmt.Errorf("the core-version part requeired 3 sections")
	}

	major, err := strconv.ParseInt(items[0], 10, 32)
	if err != nil {
		return nil, fmt.Errorf("")
	}

	minor, err := strconv.ParseInt(items[1], 10, 32)
	if err != nil {
		return nil, fmt.Errorf("")
	}

	patch, err := strconv.ParseInt(items[2], 10, 32)
	if err != nil {
		return nil, fmt.Errorf("")
	}

	return []int{int(major), int(minor), int(patch)}, nil
}

func parsePreRelease(s string) ([]string, error) {
	items := strings.Split(s, ".")
	if len(items) != 3 {
		return nil, fmt.Errorf("the pre-release part requeired 3 sections")
	}

	return items, nil
}

func parsebuildMetadata(s string) ([]string, error) {
	items := strings.Split(s, ".")
	if len(items) != 3 {
		return nil, fmt.Errorf("the build-metadata patry requeired 3 sections")
	}

	return items, nil
}

func Parse(s string) (*Version, error) {
	pos := strings.IndexAny(s, "-+")

	if pos <= 0 {
		// 无减号也无加号
		coreItems, err := parseCore(s)
		if err != nil {
			return nil, err
		}

		return &Version{
			String:        s,
			Major:         coreItems[0],
			Minor:         coreItems[1],
			Patch:         coreItems[1],
			PreRelease:    make([]string, 0),
			BuildMetadata: make([]string, 0),
		}, nil
	}

	coreItems, err := parseCore(s[:pos])
	if err != nil {
		return nil, err
	}

	if s[pos] == '+' {
		// 只有加号无减号
		buildMetadataItems, err := parsebuildMetadata(s[pos+1:])
		if err != nil {
			return nil, err
		}

		return &Version{
			String:        s,
			Major:         coreItems[0],
			Minor:         coreItems[1],
			Patch:         coreItems[1],
			PreRelease:    make([]string, 0),
			BuildMetadata: buildMetadataItems,
		}, nil
	}

	remain := s[pos+1:]
	pos2 := strings.Index(remain, "+")
	if pos2 < 0 {
		// 只有减号无加号
		preReleaseitems, err := parsePreRelease(remain)
		if err != nil {
			return nil, err
		}

		return &Version{
			String:        s,
			Major:         coreItems[0],
			Minor:         coreItems[1],
			Patch:         coreItems[1],
			PreRelease:    preReleaseitems,
			BuildMetadata: make([]string, 0),
		}, nil
	}

	// 有加号也有减号
	preReleaseitems, err := parsePreRelease(remain[:pos2])
	if err != nil {
		return nil, err
	}

	buildMetadataItems, err := parsebuildMetadata(remain[pos2+1:])
	if err != nil {
		return nil, err
	}

	return &Version{
		String:        s,
		Major:         coreItems[0],
		Minor:         coreItems[1],
		Patch:         coreItems[1],
		PreRelease:    preReleaseitems,
		BuildMetadata: buildMetadataItems,
	}, nil
}

type CompareResult = int

const (
	Unknown = CompareResult(-2) // 无法比较
	Lower   = CompareResult(-1) // 更低
	Equal   = CompareResult(0)  // 相等
	Higher  = CompareResult(1)  // 更高
)

//func Compare(ver1 *Version, ver2 *Version) CompareResult {
//
//}
